import { WebSocketServer, WebSocket } from "ws";
import { Singleton } from "../common/common/base";
import {
  AuthClient,
  CheckTokenReq,
  RpcFunc,
  ServerPort,
  getProtoPathByRpcFunc,
} from "../common";

import * as grpc from "@grpc/grpc-js";
//@ts-ignore
import root from "../common/idl/auto-gen-ws";

export class GatewayManager extends Singleton {
  static get Instance() {
    return super.GetInstance<GatewayManager>();
  }

  init() {
    const wss = new WebSocketServer({ port: ServerPort.Gateway });

    wss.on("connection", (ws) => {
      ws.on("error", function (err) {});

      ws.on("message", (buffer: Buffer) => {
        this.handleMessage(ws, buffer);
      });
    });
  }

  async handleMessage(ws: WebSocket, buffer: Buffer) {
    console.log("received message", buffer.toString());

    const name = buffer.readUInt8(0);
    const path = getProtoPathByRpcFunc(name, "req");
    const coder = root.lookup(path);
    const data = coder.decode(buffer.slice(1));

    // const { name, data } = JSON.parse(buffer.toString());
    if (name == RpcFunc.enterGame) {
      //TODO:鉴权
      const res = await this.checkToken(data);
      this.sendMessage(ws, name, res);
    } else {
      //TODO:与gameserver通讯
    }

    // ws.send(buffer.toString());
  }

  sendMessage(ws: WebSocket, name: RpcFunc, data: any) {
    const headBuffer = Buffer.alloc(1);
    headBuffer.writeUInt8(name, 0);
    const path = getProtoPathByRpcFunc(name, "res");
    const coder = root.lookup(path);
    const dataBuffer = coder.encode(data).finish();

    const buffer = Buffer.concat([headBuffer, dataBuffer]);

    ws.send(buffer);
  }

  checkToken({ token }: { token: string }) {
    return new Promise((rs) => {
      const client = new AuthClient(
        "localhost:3333",
        grpc.credentials.createInsecure()
      );

      const req = new CheckTokenReq();
      req.setToken(token);

      client.checkToken(req, (err, message) => {
        rs(message.toObject());
      });
    });
  }
}
